package jee.boot.entity.auth;


import com.fasterxml.jackson.annotation.JsonIgnore;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import jee.boot.common.annotation.Transient;
import jee.boot.common.basic.DataEntity;
import jee.boot.common.basic.ServiceException;
import jee.boot.entity.system.Filter;
import jee.boot.common.utils.StringUtils;
import jee.boot.entity.auth.standard.DataValue;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 标准模型数据交互
 */
public class StandardModel extends DataEntity<StandardModel> {
    /**
     * modelData.code 模型标识(唯一值)
     */
    @Transient
    private ModelData modelData = new ModelData();
    /**
     * 数据对象: get/save/update/delete使用的数据存储载体
     * eq: {name:{v:'张三',p:'Visible'}}
     */
    @Transient
    private Map<String, DataValue> data;
    /**
     * 数据对象: list/findPage 使用的数据存储载体
     * eq: [{name:{v:'张三',p:'Visible'}},{name:{v:'张三',p:'Visible'}}]
     */
    @Transient
    private List<Map<String, DataValue>> list;
    /**
     * 数据库查询出来的原始数据/保存进入数据库的数据,前台不可见
     */
    @Transient
    private Map<String, Object> db;
    /**
     * 数据库查询出来的原始数据/保存进入数据库的数据,前台不可见
     */
    @Transient
    private List<Map<String, Object>> dbList;
    /**
     * 拥有查询权限的column
     */
    @Transient
    private List<AuthEntity> columnPermission = Lists.newArrayList();
    /**
     * 拥有编辑权限的column
     */
    @Transient
    private List<AuthEntity> cellSetPermission = Lists.newArrayList();
    /**
     * 拥有rowSet权限
     */
    @Transient
    private List<AuthEntity> rowSetPermission = Lists.newArrayList();
    /**
     * 有查看权限的列
     */
    @Transient
    private List<Column> hasViewList;
    /**
     * 有编辑权限的列
     */
    @Transient
    private List<Column> hasEditList;
    /**
     * 导出时候使用的json头信息
     */
    @Transient
    private String exportJson;

    public StandardModel() {
    }

    public StandardModel(String id) {
        super(id);
    }

    @Override
    public String getGetSql() {
        /**
         * column.type字典
         * DIC_MT_ColumnType_CT01	维度
         * DIC_MT_ColumnType_CT02	度量
         * DIC_MT_ColumnType_CT03	主键
         * DIC_MT_ColumnType_CT99	其它
         */
        StringBuilder sql = new StringBuilder();
        String tableName = modelData.getModelTableName();
        List<Column> columnList = hasViewPermission(modelData.getColumnList());
        if (columnList.isEmpty()) {
            throw new ServiceException(1203);
        }
        StringBuilder columns = new StringBuilder();
        for (Column f : columnList) {
            columns.append("a.").append(f.getColumnName()).append(" AS ").append("\"").append(f.getCode()).append("\",");
        }

        sql.append("SELECT ");
        sql.append(StringUtils.removeEnd(columns.toString(), ","));
        sql.append(" FROM ").append(tableName).append(" a");
        sql.append(" WHERE ").append(primaryKeySql(modelData.getColumnList()));
        return sql.toString();
    }


    @Override
    public String getFindListSql() {
        StringBuilder sql = new StringBuilder();
        String tableName = modelData.getModelTableName();
        List<Column> columnList = hasViewPermission(modelData.getColumnList());
        if (columnList.isEmpty()) {
            throw new ServiceException(1203);
        }
        StringBuilder columns = new StringBuilder();
        for (Column f : columnList) {
            columns.append("a.").append(f.getColumnName()).append(" AS ").append("\"").append(f.getCode()).append("\",");
        }
        sql.append("SELECT ");
        sql.append(StringUtils.removeEnd(columns.toString(), ","));
        sql.append(" FROM ").append(tableName).append(" a");
        return sql.toString();
    }


    @Override
    public String getInsertSql() {
        StringBuilder sql = new StringBuilder();
        String tableName = modelData.getModelTableName();
        // 新增数据是否考虑不限制编辑权限??
//        List<Column> columnList = hasEditPermission(modelData.getColumnList());
        List<Column> columnList = modelData.getColumnList();
        if (columnList.isEmpty()) {
            throw new ServiceException(1203);
        }
        StringBuilder columns = new StringBuilder();
        StringBuilder values = new StringBuilder();
        for (Column f : columnList) {
            columns.append(f.getColumnName()).append(",");
            values.append("#{db.").append(f.getCode()).append("},");
        }
        sql.append("INSERT INTO ").append(tableName).append(" ( ");
        sql.append(StringUtils.removeEnd(columns.toString(), ","));
        sql.append(" ) VALUES ( ");
        sql.append(StringUtils.removeEnd(values.toString(), ",")).append(")");
        return sql.toString();
    }

    @Override
    public String getUpdateSql() {
        StringBuilder sql = new StringBuilder();
        String tableName = modelData.getModelTableName();
        List<Column> columnList = hasEditPermission(modelData.getColumnList());
        if (columnList.isEmpty()) {
            throw new ServiceException(1203);
        }
        StringBuilder columns = new StringBuilder();
        for (Column f : columnList) {
            columns.append(f.getColumnName()).append(" = ").append("#{db.").append(f.getCode()).append("},");
        }
        sql.append("UPDATE ").append(tableName).append(" SET ");
        sql.append(StringUtils.removeEnd(columns.toString(), ","));
        sql.append(" WHERE ").append(primaryKeySql(modelData.getColumnList()));
        return sql.toString();
    }

    @Override
    public String getDeleteSql() {
        String tableName = modelData.getModelTableName();
        StringBuilder sql = new StringBuilder();
        sql.append("DELETE FROM ").append(tableName);
        sql.append(" WHERE ").append(primaryKeySql(modelData.getColumnList()));
        return sql.toString();
    }

    /**
     * 根据主键字段拼接过滤sql
     *
     * @param list
     * @return
     */
    private String primaryKeySql(List<Column> list) {
        StringBuilder sb = new StringBuilder();
        if (list != null && !list.isEmpty()) {
            List<Column> typeCt03 = list.stream().filter(column -> StringUtils.equals(AuthConstant.MASTER_DATA_COLUMN_TYPE_PRIMARY_KEY, column.getType())).collect(Collectors.toList());
            if (typeCt03 != null && !typeCt03.isEmpty()) {
                for (Column column : typeCt03) {
                    sb.append(column.getColumnName()).append(" = ").append("#{db.").append(column.getCode()).append("} and");
                }
            }
        }
        if (StringUtils.isNotBlank(sb.toString())) {
            return StringUtils.removeEnd(sb.toString(), "and");
        } else {
            return " id= #{" + getId() + "}";
        }
    }

    /**
     * 过滤有查看权限的列
     *
     * @param columnList
     * @return
     */
    public List<Column> hasViewPermission(List<Column> columnList) {
        if (hasViewList != null) {
            if (columnList != null && !columnList.isEmpty()) {
                List<String> collect = hasViewList.stream().map(column -> column.getCode()).collect(Collectors.toList());
                return columnList.stream().filter(d -> collect.contains(d.getCode())).collect(Collectors.toList());
            }
        }
        return columnList;
    }

    /**
     * 过滤有编辑权限的列
     *
     * @param columnList
     * @return
     */
    private List<Column> hasEditPermission(List<Column> columnList) {
        if (hasEditList != null) {
            if (columnList != null && !columnList.isEmpty()) {
                List<String> collect = hasEditList.stream().map(column -> column.getCode()).collect(Collectors.toList());
                return columnList.stream().filter(d -> collect.contains(d.getCode())).collect(Collectors.toList());
            }
        }
        return columnList;
    }

    /**
     * db数据转换成data数
     */
    public void db2data() {
        // 当data的不为空的时候可能是在权限拦截模块进行了转换,这里就不需要转换了,当没有引入权限拦截模块的时候,这里就需要转换下
        if (data == null) {
            this.data = db2data(this.db);
        }

    }

    /**
     * data数据转换成db数据
     */
    public void data2db() {
        this.db = data2db(this.data);
    }

    /**
     * dbList数据转换成dataList数据
     */
    public void dbList2dataList() {
        // 当list的不为空的时候可能是在权限拦截模块进行了转换,这里就不需要转换了,当没有引入权限拦截模块的时候,这里就需要转换下
        if (list == null || list.isEmpty()) {
            List<Map<String, Object>> dbList = getDbList();
            if (dbList != null) {
                if (this.list == null) {
                    this.list = Lists.newArrayList();
                }
                for (Map<String, Object> db : dbList) {
                    Map<String, DataValue> db2data = db2data(db);
                    this.list.add(db2data);
                }
            }
        }
    }

    /**
     * 数据库查询的数据增加权限信息转换为页面需要的数据
     *
     * @param db
     * @return
     */
    private Map<String, DataValue> db2data(Map<String, Object> db) {
        Map<String, DataValue> map = Maps.newHashMap();
        if (db != null && !db.isEmpty()) {
            db.forEach((key, value) -> {
                // TODO 这里实际上要根据权限来筛选出当前数据是什么权限,暂时先写死一个只读权限吧
                map.put(key, new DataValue(value, "Visible"));
            });
        }
        return map;
    }

    /**
     * 将页面的数据信息提取出有效数据,转成数据库使用的数据
     *
     * @param data
     * @return
     */
    private Map<String, Object> data2db(Map<String, DataValue> data) {
        Map<String, Object> map = Maps.newHashMap();
        if (data != null && !data.isEmpty()) {
            data.forEach((key, value) -> {
                map.put(key, value.getV());
            });
        }
        return map;
    }

    @Override
    public String getColumnByFieldName(String fieldName) {
        List<Column> columnList = modelData.getColumnList();
        if (columnList != null && !columnList.isEmpty()) {
            for (Column column : columnList) {
                if (StringUtils.equals(column.getCode(), fieldName)) {
                    return "a." + column.getColumnName();
                }
            }
        }
        return fieldName;
    }

    public String getModel() {
        return modelData.getName();
    }

    public void setModel(String model) {
        this.modelData.setCode(model);
    }

    public ModelData getModelData() {
        return modelData;
    }

    public void setModelData(ModelData modelData) {
        this.modelData = modelData;
    }

    public Map<String, DataValue> getData() {
        return data;
    }

    public void setData(Map<String, DataValue> data) {
        this.data = data;
    }

    public List<Map<String, DataValue>> getList() {
        return list;
    }

    public void setList(List<Map<String, DataValue>> list) {
        this.list = list;
    }

    @JsonIgnore
    public Map<String, Object> getDb() {
        return db;
    }

    public void setDb(Map<String, Object> db) {
        this.db = db;
    }

    public List<Map<String, Object>> getDbList() {
        return dbList;
    }

    public void setDbList(List<Map<String, Object>> dbList) {
        this.dbList = dbList;
    }

    public void setColumnPermission(List<AuthEntity> columnPermission) {
        this.columnPermission = columnPermission;
    }

    public void setCellSetPermission(List<AuthEntity> cellSetPermission) {
        this.cellSetPermission = cellSetPermission;
    }

    public void setRowSetPermission(List<AuthEntity> rowSetPermission) {
        this.rowSetPermission = rowSetPermission;
    }

    public void setHasViewList(List<Column> hasViewList) {
        this.hasViewList = hasViewList;
    }

    public void setHasEditList(List<Column> hasEditList) {
        this.hasEditList = hasEditList;
    }

    @JsonIgnore
    public List<AuthEntity> getColumnPermission() {
        return columnPermission;
    }

    @JsonIgnore
    public List<AuthEntity> getCellSetPermission() {
        return cellSetPermission;
    }

    @JsonIgnore
    public List<AuthEntity> getRowSetPermission() {
        return rowSetPermission;
    }

    @JsonIgnore
    public List<Column> getHasViewList() {
        return hasViewList;
    }

    @JsonIgnore
    public List<Column> getHasEditList() {
        return hasEditList;
    }

    @Override
    public String getTableName() {
        return getModelData().getModelTableName();
    }

    public String getExportJson() {
        return exportJson;
    }

    public void setExportJson(String exportJson) {
        this.exportJson = exportJson;
    }

    public static void main(String[] args) {
        ModelData modelData = new ModelData();
        modelData.setModelTableName("test_table");
        modelData.setColumnList(new ArrayList<Column>() {{
            add(new Column("st_user_name", "userName"));
            add(new Column("st_user_code", "userCode"));
            add(new Column("st_user_type", "userType"));
        }});
        StandardModel standardModel = new StandardModel();
        standardModel.setModelData(modelData);
        System.out.println(standardModel.getGetSql());
        System.out.println(standardModel.getFindListSql());
        System.out.println(standardModel.getInsertSql());
        System.out.println(standardModel.getUpdateSql());
        System.out.println(standardModel.getDeleteSql());
        User user = new User();
        user.addFilter(new Filter("email", "left like", "1"));
        user.addFilter(new Filter("email", "right like", "2"));
        user.addFilter(new Filter("email", "not like", "3"));
        System.out.println(user.getWhere());
    }

}
